// 定义模块管理器单体对象
var F = F || {};

/**
 * 定义模块的方法（理论上方法应该放在闭包中实现，可以隐藏内部信息这里我们为让读者可以看明白，我们忽略此步骤）
 * @param  str 模块路由，如string、string.trim
 * @param  fn  模块方法实现
 */
F.define = function(str, fn) {
		// 解析模块路由
	var parts = str.split('.'),
		// old 当前模块的祖父模块，parent 当前模块父模块
		// 如果在闭包中，为了屏蔽对模块直接访问，建议将模块添加给闭包内部私有变量
		old = parent = this,
		i = len = 0;
	// 如果第一个模式是模块管理器单体对象，则移除
	if (parts[0] === 'F') {
		parts = parts.slice(1);
	}
	// 屏蔽对 define 与 module 模块方法的重写
	if (parts[0] === 'define' || parts[0] === 'module') {
		return;
	}
	// 遍历路由模块并定义每层模块
	for (len = parts.length; i < len; i++) {
		// 如果父模块中不存在当前模块
		if (typeof parent[parts[i]] === 'undefined') {
			// 声明当前模块
			parent[parts[i]] = {};
		}
		// 缓存下一层级的祖父模块
		old = parent;
		// 缓存下一层级父模块
		parent = parent[parts[i]];
	}
	// 如果给定模块方法则定义该模块方法
	if (fn) {
		// 此时 i 等于 parts.length，故减一
		old[parts[--i]] = fn();
	}
	// 返回模块管理器单体对象
	return this;
}

// 模块调用方法
F.module = function() {
		// 将参数转化为数组
	var args = [].slice.call(arguments),
		// 获取回调执行函数
		fn = args.pop(),
		// 获取依赖模块，如果args[0] 是数组，则依赖模块为args[0]。否则依赖模块为args
		parts = args[0] && args[0] instanceof Array ? args[0] : args,
		// 依赖模块列表
		modules = [],
		// 模块路由
		modIDs = '',
		// 依赖模块索引
		i = 0,
		// 依赖模块长度
		ilen = parts.length,
		// 父模块，模块路由层级索引，模块路由层级长度
		parent, j, jlen;
	// 遍历依赖模块
	while(i < ilen) {
		// 如果是路由模块
		if (typeof parts[i] === 'string') {
			// 设置当前模块父对象（F）
			parent = this;
			// 解析模块路由，并屏蔽掉模块父对象
			modIDs = parts[i].replace(/^F\./, '').split('.');
			// 遍历模块路由层级
			for (j = 0, jlen = modIDs.length; j < jlen; j++) {
				// 重置父模块
				parent = parent[modIDs[j]] || false;
			}
			// 将模块添加到依赖模块列表中
			modules.push(parent);
		// 如果是对象
		} else {
			// 直接加入依赖模块列表中
			modules.push(parts[i]);
		}
		// 取下一个依赖模块
		i++;
	}
	// 执行回调执行函数
	fn.apply(null, modules);
}

// 定义 F.string 模块
F.define('string', function() {
	// 接口方法
	return {
		// 清除字符串两边空白
		trim: function(str) {
			return str.replace(/^\s+|\s+$/g, '');
		}
	}
});

// 定义 F.dom 模块
F.define('dom', function() {
	// 简化获取元素方法（重复获取可被替代，此设计用于演示模块添加）
	var $ = function(id) {
		$.dom = document.getElementById(id);
		// 返回构造函数对象
		return $;
	}
	// 获取或者设置元素内容
	$.html = function(html) {
		if (html) {
			this.dom.innerHTML = html;
			return this;
		} else {
			return this.dom.innerHTML;
		}
	}
	// 返回构造函数
	return $;
});
